package com.soil.code.generation.database.factory;

import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.mybatis.FlexConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.Objects;

/**
 * @author zeno
 */
public class FlexBootstrapFactory{

  public static final String ENVIRONMENT_ID = "code-generation";

  public static MybatisFlexBootstrap createFlexBootstrap(
    DataSource ds,String mappersLocation,String... mapperPackages ) throws IOException{

    JdbcTransactionFactory jdbcTransactionFactory = new JdbcTransactionFactory();
    Environment environment = new Environment(ENVIRONMENT_ID,jdbcTransactionFactory,ds);
    FlexConfiguration flexConfiguration = new FlexConfiguration(environment);
    for(String mapperPackage: mapperPackages){
      flexConfiguration.addMappers(mapperPackage);
    }

    if( !Objects.isNull(mappersLocation) ){
      parseMappers(flexConfiguration,mappersLocation);
    }

    MybatisFlexBootstrap bootstrap = new MybatisFlexBootstrap();
    bootstrap.setDataSource(ds);
    bootstrap.setConfiguration(flexConfiguration);

    FlexGlobalConfig.getDefaultConfig().setPrintBanner(false);

    Logger logger = LoggerFactory.getLogger(FlexBootstrapFactory.class);
    if( logger.isDebugEnabled() ){
      bootstrap.setLogImpl(StdOutImpl.class);
    }
    return bootstrap.start();
  }

  private static Resource[] mappersLocation( String locationPattern ) throws IOException{

    ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
    return resourceResolver.getResources(locationPattern);
  }

  private static void parseMappers(
    FlexConfiguration config,String locationPattern ) throws IOException{

    Logger logger = LoggerFactory.getLogger(FlexBootstrapFactory.class);

    Resource[] resources = mappersLocation(locationPattern);
    for(Resource resource: resources){
      if( resource == null ){
        continue;
      }

      try{
        XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(),config
          ,resource.toString(),config.getSqlFragments());
        xmlMapperBuilder.parse();
      } catch(Exception e){
        logger.error("Mybatis Mapper.xml 解析异常：" + resource.getFilename(),e);
      } finally{
        ErrorContext.instance().reset();
      }
    }
  }

}
